import 'dart:async';
import 'dart:convert';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:ui' as dartUi;
import 'package:flutter_overlay_window/flutter_overlay_window.dart';
import 'package:get/get.dart';
import 'package:path_provider/path_provider.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:smart_translator/app/event/DataCallBack.dart';
import 'package:system_alert_window/system_alert_window.dart';
import '../algorithm/RealtimePcmToWavConverter.dart';
import 'package:web_socket_client/web_socket_client.dart' as ws;
import '../db/DbDAOHelper.dart';
import '../manager/AudioStreamManager.dart';
import '../modules/listenerTranslation/controllers/listener_translation_controller.dart';
import '../utils/CommonUtil.dart';
import '../utils/tips.dart';

//专门用户处理app全局audio服务.
class AudioService extends GetxService {

  Timer? _timer;
  ws.WebSocket? realTranlationSocket;


  bool wsServerHaveReady = false;
  bool hasInitRecord = false;

  // 是否在首页, 首页的只给
  bool isAtIndexPage = false;

  String audioFilePath = '';
  RealtimePcmToWavConverter? converter;
  String? sessionId;

  Timer? _recordTimer;
  int recordingSecond = 0;
  var recordShowSeconds = ''.obs;

  int BUSSINESS_TYPE = 0; //0 表示首页直译, 1表示实时翻译, 2 听译, 3. 会议转写.


  String fromLanguage = 'zh-CN';
  String toLanguage = 'en-US';
  var fromLanFlagDisplay = '中文（普通话，中国大陆）'.obs;
  var toLanFlagDisplay = '英语（美国）'.obs;


  String transFromLanguage = '';
  String transToLanguage = '';

  String tempFromLanguage = '';
  String tempToLanguage = '';

  var finalFromLanguage = ''.obs;
  var finalToLanguage = ''.obs;

  var indexPageFinalFromLanguage = ''.obs;
  var indexPageFinalToLanguage = ''.obs;

  String? taskId;


  var isPlaying = false.obs;

  var recordingDataController;


  SendPort? mainAppPort;
  static const String _mainAppPort = 'MainApp';


  AudioStreamManager audioStreamManager = AudioStreamManager();

  int changeLineCount = 0;


  static SystemWindowPrefMode prefMode = SystemWindowPrefMode.DEFAULT;

  var showLogText = "".obs;
  int recorderAudioSize = 0;

  bool audioServiceHasStart = false;

  AudioService init() {
    // audioStreamManager.initService();
    return this;
  }


  void onClose() {
    super.onClose();


    if (_timer != null) {
      _timer!.cancel();
    }

    if (_recordTimer != null) {
      _recordTimer!.cancel();
    }

    if (recordShowSeconds != null) {
      realTranlationSocket!.close();
    }

  }


  initAllState () {
    wsServerHaveReady = false;
    hasInitRecord = false;

    isAtIndexPage = false;
    /*//语言清除
    fromLanguage = '';
    toLanguage = '';*/

    transFromLanguage = '';
    transToLanguage = '';

    tempFromLanguage = '';
    tempToLanguage = '';
    recordingSecond = 0;

    isPlaying.value = false;
    finalFromLanguage.value = '';
    finalToLanguage.value = '';
    recordShowSeconds.value = '';

    indexPageFinalFromLanguage.value = '';
    indexPageFinalToLanguage.value = '';
  }


  initAllStateForEnding () {
    wsServerHaveReady = false;
    hasInitRecord = false;
    isAtIndexPage = false;
    //语言清除
   /* fromLanguage = '';
    toLanguage = '';*/

    transFromLanguage = '';
    transToLanguage = '';

    tempFromLanguage = '';
    tempToLanguage = '';
    recordingSecond = 0;

    //防止obx刷新和框架自主刷新冲突,延后1s.
    Future.delayed(Duration(milliseconds: 500), () {
      isPlaying.value = false;

      finalFromLanguage.value = '';
      finalToLanguage.value = '';

      indexPageFinalFromLanguage.value = '';
      indexPageFinalToLanguage.value = '';
    });

  }

  void reInitWs() {
    if (realTranlationSocket != null) {
      realTranlationSocket!.send({
        'end': true
      });
      realTranlationSocket!.close();
      realTranlationSocket = null;
    }

    realTranlationSocket = null;
  }


  void connectedWsAndRecorder(String url, DataCallBack dataCallBack) async {
    Tips.showLoading();
    if (realTranlationSocket != null) {
      realTranlationSocket!.send(json.encode({
        'end': true
      }));
      realTranlationSocket!.close();
      realTranlationSocket = null;
    }

    print('ws socket 请求url:' + url+'&from=${fromLanguage}&to=${toLanguage}');
    realTranlationSocket = ws.WebSocket (Uri.parse(url+'&from=${fromLanguage}&to=${toLanguage}'),
        headers: {
          'x-api-key': '264e03da4958e5ea405dd8f63b87da898757b821',
          // 'x-app-id': 'RquRazmzJpXLdp84'
        },
        timeout: Duration(seconds: 20));



    realTranlationSocket!.connection.listen((v) {
      print('center connection  status: ${v}');

      // 处理断掉重连.

    });

    realTranlationSocket!.messages.listen((v) async {
      print('center message from server : ${v}');
      if (v == 'ok') return;
      Map result = json.decode(v.toString());
      if(result['action'] == 'started') {
        taskId = result['taskId'];
        //发送心跳包.
        _timer = Timer.periodic(Duration(seconds: 7), (timer) {
          if(realTranlationSocket != null)
          realTranlationSocket!.send('Heartbeat'); //

        });

        // 服务器已经Ready了.
        wsServerHaveReady = true;

        if (!hasInitRecord) {
          hasInitRecord  = true;
          await initRecorderService(dataCallBack);

        } else { // 语言切换场景,recorder已经初始化过了.
          Tips.dismissLoading();
          if (dataCallBack.confirmCallBack != null) {
            dataCallBack.confirmCallBack!('');
          }

        }

      } else if (result['action'] == 'result') {
        if (dataCallBack.sessionCallBack != null) {
            dataCallBack.sessionCallBack!(result);
            return;
        }

        // 服务器转写结果.
        if(result['finish'] == true) {
          if(result['srcCode'] == fromLanguage) {
            transFromLanguage = transFromLanguage + result['text'];
            transToLanguage = transToLanguage + result['translation'];
          } else {
            transFromLanguage = transFromLanguage + result['translation'];
            transToLanguage = transToLanguage + result['text'];
          }

          changeLineCount = changeLineCount + 1;
          if (changeLineCount > 10 && !isAtIndexPage) {
            transFromLanguage = transFromLanguage + '\n\n';
            transToLanguage = transToLanguage + '\n\n';
            changeLineCount = 0;
          }


          if (isAtIndexPage) {
            indexPageFinalFromLanguage.value = transFromLanguage.trim();
            indexPageFinalToLanguage.value = transToLanguage.trim();
          } else {
            finalFromLanguage.value = transFromLanguage.trim();
            finalToLanguage.value = transToLanguage.trim();

          }


        } else {
          if(result['srcCode'] == fromLanguage) {
            tempFromLanguage = transFromLanguage + result['text'];
            tempToLanguage = transToLanguage + result['translation'];
          } else {
            tempFromLanguage = transFromLanguage + result['translation'];
            tempToLanguage = transToLanguage + result['text'];
          }



          if (isAtIndexPage) {
            indexPageFinalFromLanguage.value = transFromLanguage.trim();
            indexPageFinalToLanguage.value = transToLanguage.trim();
          } else {
            finalFromLanguage.value = tempFromLanguage.trim();
            finalToLanguage.value = tempToLanguage.trim();
          }

        }

        mainAppPort = dartUi.IsolateNameServer.lookupPortByName(
            _mainAppPort,
        );

        print('finalToLanguage ----> ${finalToLanguage}');
        print('finalFromLanguage ----> ${finalFromLanguage}');
        print('mainAppPort ----> ${mainAppPort}');

        /*mainAppPort?.send({
          'finalFromLanguage': finalFromLanguage.value,
          'finalToLanguage': finalToLanguage.value
        });*/

        bool isListenerHasRegister = Get.isRegistered<ListenerTranslationController>();
        if (isListenerHasRegister) {
          ListenerTranslationController listenerTranslationController = Get.find<ListenerTranslationController>();
          int contentType = listenerTranslationController.listenerContentType.value;
          if (contentType == 0) {
            FlutterOverlayWindow.shareData({
              'finalFromLanguage': finalFromLanguage.value
            });
          } else if (contentType == 1) {
            FlutterOverlayWindow.shareData({
              'finalToLanguage': finalToLanguage.value
            });
          } else {
            FlutterOverlayWindow.shareData({
              'finalFromLanguage': finalFromLanguage.value,
              'finalToLanguage': finalToLanguage.value
            });
          }

        } else {
          FlutterOverlayWindow.shareData({
            'finalFromLanguage': finalFromLanguage.value,
            'finalToLanguage': finalToLanguage.value
          });
        }

        if (dataCallBack.businessCallBack != null) {
          dataCallBack.businessCallBack!('v');
        }


      }
    });

    await realTranlationSocket!.connection.firstWhere((state) => state is ws.Connected);
  }


  Future<void> initRecorderService(DataCallBack dataCallBack) async {
    var status = await Permission.microphone.request();
    if (status != PermissionStatus.granted) {
      Tips.showToast('Microphone permission not granted');
    }


    var storageStatus = await Permission.storage.request();
    if (storageStatus != PermissionStatus.granted) {
      var storageStatus2 = await Permission.manageExternalStorage.request();
      if (storageStatus2 != PermissionStatus.granted) {
        Tips.showToast('Storage permission not granted');
      }
    }


    final tempDir = await getTemporaryDirectory();
    audioFilePath = '${tempDir.path}/zhiyi_record2script${DateTime.now().millisecondsSinceEpoch}.wav';

    converter = RealtimePcmToWavConverter(
        outputPath: audioFilePath,
        sampleRate: 16000,
        numChannels: 1
    );

    Tips.dismissLoading();

    if (dataCallBack.deviceCallBack != null) {
      dataCallBack.deviceCallBack!({});
    }


  }

  Future<void> record({DataCallBack? callback}) async {
   isPlaying.value = true;

   recorderAudioSize = 0;
   showLogText.value = '';

   await audioStreamManager.startRecording();

   Future.delayed(Duration(seconds: 1),() {
     audioStreamManager.audioStream.listen((data) {
       print('begin buffer.length: ${data.length}');


       var audioData = data['audioData'] as List<int>;
       //音频振幅.
       var amplitude = data['amplitude'];

       if (callback != null) {
           callback.confirmCallBack!(amplitude);
       }



       //print('real audio data: ${data['audioData']}');
       print('amplitude data: ${data['amplitude']}');


       recorderAudioSize = recorderAudioSize + audioData.length;
       showLogText.value = 'buffer size: ${data.length}, buffer.length: ${recorderAudioSize},  time: ${CommonUtil.formatCustomWeekday(DateTime.now())}';
       writeAuto2File(Uint8List.fromList(audioData));

       if (wsServerHaveReady && isPlaying.value) {
         realTranlationSocket!.send(audioData);
         print('end buffer.length: ${audioData.length}');

       } else {
         print('center ws 未就绪, 或者recorder已经暂停.');

       }
     });
   });


   _recordTimer = Timer.periodic(Duration(seconds: 1), (timer) {
     if (isPlaying.value) {
       recordingSecond = recordingSecond + 1;
       recordShowSeconds.value = CommonUtil.formatMillisecondsToHHMMSS(recordingSecond);
     }});

  }

  writeAuto2File(Uint8List byteData)  {
    Future.microtask((){
      if (converter != null) {
        converter!.writeChunk(byteData);
      }
    });

  }

  Future<void> stopRecorder() async {
    if (realTranlationSocket != null) {
      realTranlationSocket!.send(json.encode({
        'end': true
      }));
      realTranlationSocket!.close();
      realTranlationSocket = null;
    }

    if (_recordTimer != null) {
      _recordTimer!.cancel();
    }

    if (_timer != null) {
      _timer!.cancel();
    }

    realTranlationSocket = null;


    //停止录音
    await audioStreamManager.stopRecording();

    Future.microtask(() {
      //文件转换结束.
      if (converter != null) {
        converter!.finalize();
      }
    });

    initAllStateForEnding();
  }



  Future<void> stopRecorderForIndex () async {
    wsServerHaveReady = false;
    hasInitRecord = false;

    isPlaying.value = false;
    isAtIndexPage = false;

    if (realTranlationSocket != null) {
      realTranlationSocket!.send(json.encode({
        'end': true
      }));
      realTranlationSocket!.close();
      realTranlationSocket = null;
    }

    realTranlationSocket = null;


    audioStreamManager.stopRecording();

    //文件转换结束.
    if (converter != null) {
      converter!.finalize();
    }
  }


  Future<void> pauseRecorder() async {
    isPlaying.value = false;

    Future.microtask(() {
      audioStreamManager.stopRecording();
    });
  }


  void saveTranslationRecords(String taskId, int translationActionType) {
    if (finalFromLanguage.value.trim() != '' && finalToLanguage.value.trim() != '') {
      DbDAOHelper().saveTranslateHistory(fromLanguage, toLanguage,
          finalFromLanguage.value, finalToLanguage.value, taskId ?? '01010101010101',translationActionType,fromLanFlagDisplay.value,toLanFlagDisplay.value
          );
    }

  }

  void exchangeLanguages({DataCallBack? callBack}) {
     String temp = fromLanguage;
     fromLanguage = toLanguage;
     toLanguage = temp;

     String tempDisplay = fromLanFlagDisplay.value;
     fromLanFlagDisplay.value = toLanFlagDisplay.value;
     toLanFlagDisplay.value = tempDisplay;

     String indexTempDisplay = indexPageFinalFromLanguage.value;
     indexPageFinalFromLanguage.value = indexPageFinalToLanguage.value;
     indexPageFinalToLanguage.value = indexTempDisplay;

     if (callBack != null) {
       callBack!.businessCallBack!('');
     }
  }

}

